#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
类型系统核心模块

包含类型解析、类型兼容性检查等核心功能。
"""

import re
from typing import TYPE_CHECKING, List, Optional, Tuple
from mcpy.symbol_meta import SymbolKind, TypeInfo, Symbol, TypeKind

if TYPE_CHECKING:
    from .ir import IRNode
    from .symbol_registry import SymbolRegistry


# ============================================================================
# 类型兼容性规则（Type Compatibility Rules）
# ============================================================================

# 注意：当前实现中，所有泛型类型都是不变的（invariant）
# 即：泛型参数必须完全匹配，不允许 list[int] -> list[Any] 这样的转换
#
# 未来扩展：
# 如果需要支持协变（covariant）或逆变（contravariant），可以：
# 1. 在类型配置中添加 "type_variance" 字段（"invariant" | "covariant" | "contravariant"）
# 2. 通过 _get_type_variance() 函数查询类型的变型性
# 3. 根据变型性调整类型参数的兼容性检查
#
# 示例（未来）：
#   - Callable[[T], R]: T 是逆变的，R 是协变的
#   - Iterable[T]: T 是协变的（只读）
#   - list[T]: T 是不变的（可变容器）


def _get_type_symbol(
    type_info: TypeInfo, node: Optional["IRNode"] = None
) -> Optional[Symbol]:
    """获取类型对应的符号信息

    Args:
        type_info: 类型信息
        node: 上下文节点（用于符号查找）

    Returns:
        类型符号，如果找不到则返回 None
    """
    if not type_info or not type_info.name:
        return None

    # 尝试从节点上下文查找
    if node is not None:
        try:
            symbol = node.lookup_symbol(type_info.name, symbol_kinds=[SymbolKind.CLASS])
            if symbol:
                return symbol
        except Exception:
            pass

    # 尝试从全局注册表查找
    try:
        from .symbol_registry import get_global_registry

        registry = get_global_registry()
        # 使用 lookup_type_symbol 方法
        return registry.lookup_type_symbol(type_info.name)
    except Exception:
        return None


def _satisfies_protocol(
    type_info: TypeInfo, protocol_name: str, node: Optional["IRNode"] = None
) -> bool:
    """检查类型是否满足指定协议

    Args:
        type_info: 类型信息
        protocol_name: 协议名称（如 "Number", "Integer"）
        node: 上下文节点（用于符号查找）

    Returns:
        是否满足协议
    """
    symbol = _get_type_symbol(type_info, node)
    if not symbol or not symbol.type_info:
        return False

    # 检查类型配置中的协议列表
    if hasattr(symbol, "type_config") and symbol.type_config:
        protocols = symbol.type_config.get("protocols", [])
        if protocol_name in protocols:
            return True

        satisfies = symbol.type_config.get("satisfies_protocols", [])
        return protocol_name in satisfies

    return False


def is_number_type(type_info: TypeInfo, node: Optional["IRNode"] = None) -> bool:
    """检查类型是否为数值类型

    数值类型包括满足 Integer 或 Number 协议的类型。
    例如：int, float, int32_t, int64_t, double 等。

    Args:
        type_info: 类型信息
        node: 上下文节点（用于符号查找）

    Returns:
        是否为数值类型
    """
    return _satisfies_protocol(type_info, "Integer", node) or _satisfies_protocol(
        type_info, "Number", node
    )


def is_protocol_implementation(
    protocol_type: TypeInfo,
    actual_type: TypeInfo,
    node: Optional["IRNode"] = None,
) -> bool:
    """检查实际类型是否实现了 Protocol

    使用符号系统的 _satisfies_protocol 检查，而不是硬编码。

    Args:
        protocol_type: Protocol 类型（如 Iterable[T]）
        actual_type: 实际类型（如 list[int]）
        node: 上下文节点（用于符号查找）

    Returns:
        bool: 是否实现了 Protocol
    """
    # 首先检查 protocol_type 是否真的是 Protocol
    if not is_protocol_type(protocol_type, node):
        return False

    # 使用符号系统检查 actual_type 是否满足该 Protocol
    return _satisfies_protocol(actual_type, protocol_type.name, node)


def is_callable_compatible(expected: TypeInfo, actual: TypeInfo) -> bool:
    """检查 Callable 协议的类型兼容性

    用于验证实际的函数/lambda 类型是否符合 Callable 协议的约束。

    Args:
        expected: 期望的 Callable 类型（如 Callable[[int], str]）
        actual: 实际的函数类型（如 lambda[int, int]）

    Returns:
        bool: 是否兼容
    """
    # 检查期望类型是否是 Callable 协议
    if expected.name != "Callable":
        return True  # 不是 Callable，跳过特殊检查

    # 检查实际类型是否是函数类型
    if actual.kind != TypeKind.FUNCTION:
        return False  # Callable 期望函数，但实际不是

    # 检查参数数量
    expected_param_count = len(expected.args) if expected.args else 0
    actual_param_count = len(actual.args) if actual.args else 0

    if expected_param_count != actual_param_count:
        return False  # 参数数量不匹配

    # TODO: 可以进一步检查参数类型和返回类型的兼容性
    # 但由于 TypeVar 的存在，这需要更复杂的类型统一（unification）
    # 当前版本先检查参数数量即可捕获大部分错误

    return True


def types_compatible(
    type1: TypeInfo, type2: TypeInfo, node: Optional["IRNode"] = None
) -> bool:
    """检查两个类型是否兼容

    基于协议的类型兼容性检查，支持：
    - 名称和 kind 相同的类型
    - Any 类型与任意类型
    - Callable 协议与函数类型
    - Integer 协议类型互相兼容（int, int32_t, int64_t 等）
    - Number 协议类型互相兼容（int, float, double 等，包含 Integer）
    - Iterable 协议类型可转换为 list

    Args:
        type1: 第一个类型
        type2: 第二个类型
        node: 上下文节点（用于通过 lookup_symbol 查找类型符号）

    Returns:
        是否兼容
    """
    # 完全相同的类型
    if type1.name == type2.name and type1.kind == type2.kind:
        return True

    # Any 类型兼容所有类型
    if type1.kind == TypeKind.ANY or type2.kind == TypeKind.ANY:
        return True

    # None 类型兼容 Optional[T]
    # Optional[T] 在 Python 中就是 Union[T, None]，所以 None 应该能赋值给 Optional[T]
    if type1.name == "Optional" and type1.kind == TypeKind.GENERIC:
        if type2.kind == TypeKind.NONE:
            return True

    # 反向：Optional[T] 兼容 None（虽然不太常见，但为了对称性）
    if type2.name == "Optional" and type2.kind == TypeKind.GENERIC:
        if type1.kind == TypeKind.NONE:
            return True

    # Callable 协议兼容所有函数类型（lambda、function）
    if type1.name == "Callable" and type2.kind == TypeKind.FUNCTION:
        return True  # 协议兼容性在 is_callable_compatible 中详细检查

    # 反向：函数类型兼容 Callable 协议
    if type2.name == "Callable" and type1.kind == TypeKind.FUNCTION:
        return True

    # 数值类型兼容性：所有数值类型互相兼容
    # 数值类型包括 Integer 和 Number 协议（Integer ⊆ Number）
    # 例如：int ↔ float, int32_t ↔ double, int64_t ↔ int
    if is_number_type(type1, node) and is_number_type(type2, node):
        return True

    # 可迭代类型兼容性：任何满足 Iterable 协议的类型都可以转换为 list
    # 例如：dict_keys → list, dict_values → list
    if type1.name == "list":
        if _satisfies_protocol(type2, "Iterable", node):
            return True

    # Coroutine协议兼容性：任何满足Coroutine协议的类型都可以传给期望Coroutine的参数
    # 例如：result[int] → Coroutine[Any, Any, int]
    if type1.name == "Coroutine":
        if _satisfies_protocol(type2, "Coroutine", node):
            return True

    # 反向：期望具体类型，传入Coroutine协议类型
    if type2.name == "Coroutine":
        if _satisfies_protocol(type1, "Coroutine", node):
            return True

    return False


def format_type_info(type_info: TypeInfo) -> str:
    """格式化 TypeInfo 为字符串

    Args:
        type_info: 类型信息

    Returns:
        格式化的类型字符串

    Examples:
        >>> format_type_info(TypeInfo(name="int"))
        'int'

        >>> format_type_info(TypeInfo(name="list", args=[TypeInfo(name="int")]))
        'list[int]'
    """
    if type_info.kind == TypeKind.GENERIC and type_info.args:
        args_str = ", ".join(format_type_info(arg) for arg in type_info.args)
        return f"{type_info.name}[{args_str}]"
    return type_info.name


def is_generic_type(type_str: str) -> bool:
    """检查类型字符串是否为泛型类型"""
    return "[" in type_str and "]" in type_str


def _split_type_args(args_str: str) -> list[str]:
    """按逗号分割类型参数，考虑嵌套括号

    Args:
        args_str: 类型参数字符串，如 "int, int" 或 "List[int], str"

    Returns:
        分割后的参数列表

    Examples:
        >>> _split_type_args("int, int")
        ['int', 'int']
        >>> _split_type_args("List[int], str")
        ['List[int]', 'str']
    """
    args = []
    bracket_count = 0
    current_arg = ""

    for char in args_str:
        if char == "," and bracket_count == 0:
            t = current_arg.strip()
            if t:
                args.append(t)
            current_arg = ""
        else:
            if char == "[":
                bracket_count += 1
            elif char == "]":
                bracket_count -= 1
            current_arg += char

    # 添加最后一个参数
    if current_arg.strip():
        args.append(current_arg.strip())

    return args


def decode_generic_type_str(type_str: str) -> tuple[str, list[str]]:
    """解码泛型类型"""

    s = type_str.strip()
    match = re.match(r"^([a-zA-Z_][a-zA-Z0-9_]*)(\[(.+)\])?$", s)
    if not match:
        return type_str, []

    base_name = match.group(1)
    type_args_str = match.group(3)
    if not type_args_str:
        # 非泛型
        return base_name, []

    # 使用统一的分割函数
    type_args = _split_type_args(type_args_str)
    return base_name, type_args


def parse_type_with_context(
    annotation: str,
    node: Optional["IRNode"] = None,
    registry: Optional["SymbolRegistry"] = None,
) -> TypeInfo:
    """感知符号系统的类型解析函数

    这个函数优先从符号系统查找类型（特别是 TypeVar），
    能够正确识别 TypeVar 的约束信息，避免丢失类型信息。

    Args:
        annotation: 类型注解字符串，如 'int', 'list[T]', 'T'
        node: 上下文 IR 节点，用于作用域查找
        registry: 符号注册表，用于全局类型查找

    Returns:
        解析后的 TypeInfo 对象

    Examples:
        >>> # 在没有上下文时，T 会被当作 PRIMITIVE（回退到字符串解析）
        >>> parse_type_with_context("T")
        TypeInfo(kind=TypeKind.PRIMITIVE, name="T")

        >>> # 使用上下文后，T 会被正确识别为 TYPE_PARAM
        >>> parse_type_with_context("T", registry=global_registry)
        TypeInfo(kind=TypeKind.TYPE_PARAM, name="T")
    """
    # 处理特殊类型
    if annotation == "Any":
        return TypeInfo.any()

    if not annotation or annotation == "None":
        return TypeInfo.none()

    # 解析泛型类型（递归处理类型参数）
    if is_generic_type(annotation):
        base_name, type_str_args = decode_generic_type_str(annotation)

        # 特殊处理：Callable[[param_types], return_type]
        if base_name == "Callable" and len(type_str_args) >= 2:
            # 第一个参数是参数列表（带方括号）
            param_list_str = type_str_args[0].strip()
            return_type_str = type_str_args[1].strip()

            # 解析参数列表
            param_types = []
            if param_list_str.startswith("[") and param_list_str.endswith("]"):
                # 去除外层方括号
                param_list_str = param_list_str[1:-1]
                # 按逗号分割（考虑嵌套括号）
                param_strs = _split_type_args(param_list_str)
                param_types = [
                    parse_type_with_context(p.strip(), node, registry)
                    for p in param_strs
                ]

            # 解析返回类型
            return_type = parse_type_with_context(return_type_str, node, registry)

            # 构造 Callable 的 TypeInfo
            # args 存储参数类型，return_type 存储返回类型
            return TypeInfo(
                kind=TypeKind.GENERIC,
                name="Callable",
                args=param_types,
                return_type=return_type,
            )

        # 特殊处理：lambda 类型是函数类型，不是泛型类型
        # lambda[Args] 中的 Args 是参数类型列表
        if base_name == "lambda":
            type_args = [
                parse_type_with_context(arg.strip(), node, registry)
                for arg in type_str_args
            ]
            # lambda 类型没有显式的返回类型在字符串中，返回类型是 Unknown
            return TypeInfo(
                kind=TypeKind.FUNCTION,
                name="lambda",
                args=type_args,
                return_type=TypeInfo.unknown(),
            )

        # 普通泛型类型
        # 特殊处理：tuple[()] 表示空元组，参数应该为空列表
        if (
            base_name == "tuple"
            and len(type_str_args) == 1
            and type_str_args[0].strip() == "()"
        ):
            return TypeInfo(kind=TypeKind.GENERIC, name=base_name, args=[])

        type_args = [
            parse_type_with_context(arg.strip(), node, registry)
            for arg in type_str_args
        ]
        return TypeInfo(kind=TypeKind.GENERIC, name=base_name, args=type_args)

    # 尝试从符号系统查找类型
    type_symbol = None

    # 1. 如果有 IR 节点上下文，从节点作用域查找
    if node is not None:
        try:
            # TypeVar 被注册为 TYPE_PARAM，同时也要查找 CLASS
            type_symbol = node.lookup_symbol(
                annotation,
                symbol_kinds=[SymbolKind.CLASS, SymbolKind.TYPE_PARAM],
            )
        except Exception:
            pass

    # 2. 如果节点查找失败，尝试从注册表查找
    if type_symbol is None and registry is not None:
        try:
            # 使用 _types 字典查找（包含 TypeVar）
            type_symbol = registry._types.get(annotation)
        except Exception:
            pass

    # 3. 如果都失败，尝试从全局注册表查找
    if type_symbol is None:
        try:
            from .symbol_registry import (
                get_global_registry,
                is_global_registry_initializing,
            )

            if not is_global_registry_initializing():
                global_registry = get_global_registry()
                if registry is not global_registry:
                    type_symbol = global_registry._types.get(annotation)
        except Exception:
            pass

    # 4. 如果找到了类型符号，使用它的类型信息
    if type_symbol is not None:
        # TypeVar 符号有 type_info，直接使用
        if type_symbol.type_info is not None:
            return type_symbol.type_info

        # 其他类型符号，根据 kind 构造 TypeInfo
        if type_symbol.kind == SymbolKind.TYPE_PARAM:
            return TypeInfo(
                kind=TypeKind.TYPE_PARAM,
                name=annotation,
                template_constraints=(
                    type_symbol.type_info.template_constraints
                    if type_symbol.type_info
                    else []
                ),
                template_bound=(
                    type_symbol.type_info.template_bound
                    if type_symbol.type_info
                    else None
                ),
            )
        elif type_symbol.kind == SymbolKind.CLASS:
            return TypeInfo(kind=TypeKind.CLASS, name=annotation)

    # 5. 回退到纯字符串解析（无符号信息）
    return _parse_type_string(annotation)


def parse_type_string_with_template_context(
    annotation: str, template_params: List[str]
) -> TypeInfo:
    """解析类型字符串，识别模板参数

    Args:
        annotation: 类型注解字符串
        template_params: 模板参数列表，如 ['T', 'K', 'V']

    Returns:
        解析后的 TypeInfo 对象
    """
    # 处理特殊类型
    if annotation == "Any":
        return TypeInfo.any()

    if not annotation or annotation == "None":
        return TypeInfo.none()

    # 检查是否是模板参数
    if annotation in template_params:
        return TypeInfo(kind=TypeKind.TEMPLATE, name=annotation)

    # 解析泛型类型
    if is_generic_type(annotation):
        base_name, type_str_args = decode_generic_type_str(annotation)
        type_args = [
            parse_type_string_with_template_context(arg.strip(), template_params)
            for arg in type_str_args
        ]
        return TypeInfo(kind=TypeKind.GENERIC, name=base_name, args=type_args)

    # 基础类型
    return TypeInfo(kind=TypeKind.PRIMITIVE, name=annotation)


# 类型注解解析功能（私有）
def _parse_type_string(annotation: str) -> TypeInfo:
    """底层私有函数：纯字符串解析，不感知符号系统

    警告：此函数不应该直接调用，请使用 parse_type_with_context()

    这是一个纯粹的字符串解析函数，不涉及符号查找或配置访问。
    仅处理基本的类型字符串解析逻辑，用作最后的回退选项。

    Args:
        annotation: 类型注解字符串，如 'int', 'list[int]', 'dict[str, int]'

    Returns:
        解析后的 TypeInfo 对象
    """
    # 处理特殊类型
    if annotation == "Any":
        return TypeInfo.any()

    if not annotation or annotation == "None":
        return TypeInfo.none()

    # 解析泛型类型
    if is_generic_type(annotation):
        base_name, type_str_args = decode_generic_type_str(annotation)
        type_args = [_parse_type_string(arg.strip()) for arg in type_str_args]
        return TypeInfo(kind=TypeKind.GENERIC, name=base_name, args=type_args)

    # 基础类型
    return TypeInfo(kind=TypeKind.PRIMITIVE, name=annotation)


def _get_canonical_type_name(type_name: str, type_symbol: "Symbol") -> str:
    """获取类型的规范化名称

    如果符号是类型别名，返回其规范名称；否则返回原名称

    Args:
        type_name: 原始类型名
        type_symbol: 类型符号

    Returns:
        规范化的类型名称
    """
    # 检查符号是否是类型别名
    if type_symbol.is_type_alias and type_symbol.canonical_name:
        return type_symbol.canonical_name

    # 使用类型信息中的名称（可能已经规范化）
    if type_symbol.type_info and type_symbol.type_info.name:
        return type_symbol.type_info.name

    # 回退到原始名称
    return type_name


def _parse_generic_type_args(
    type_str_args: List[str], node: "IRNode"
) -> Tuple[List[TypeInfo], List[TypeInfo]]:
    """解析泛型类型参数

    Args:
        type_str_args: 类型参数字符串列表
        node: 上下文节点

    Returns:
        (lookup_type_args, concrete_type_args) 元组
    """
    lookup_type_args = []
    concrete_type_args = []

    for arg_str in type_str_args:
        arg_type = parse_type(arg_str.strip(), node)
        lookup_type_args.append(arg_type or TypeInfo.any())
        concrete_type_args.append(
            arg_type or TypeInfo(kind=TypeKind.TYPE_PARAM, name=arg_str.strip())
        )

    return lookup_type_args, concrete_type_args


def _parse_substituted_type(substituted_type_str: str, node: "IRNode") -> TypeInfo:
    """解析类型替换字符串

    Args:
        substituted_type_str: 替换类型字符串（如 "mc::variant"）
        node: 上下文节点

    Returns:
        解析后的 TypeInfo
    """
    # mc::variant 映射为 any 类型
    if substituted_type_str == "mc::variant":
        return TypeInfo.any()

    # 尝试解析其他类型
    parsed_type = parse_type(substituted_type_str, node)
    if parsed_type:
        return parsed_type

    # 回退：使用字符串作为类型名
    return TypeInfo(kind=TypeKind.PRIMITIVE, name=substituted_type_str)


def _build_weak_generic_type(type_config: dict, node: "IRNode") -> Optional[TypeInfo]:
    """构建弱泛型类型（如 list -> list[any]）

    Args:
        type_config: 类型配置字典
        node: 上下文节点

    Returns:
        转换后的泛型类型，如果不适用则返回 None
    """
    inherit_from = type_config.get("inherit_from")
    if not inherit_from or not is_generic_type(inherit_from):
        return None

    base_name, param_names = decode_generic_type_str(inherit_from)
    type_substitution = type_config.get("type_substitution", {})

    # 根据 type_substitution 构建类型参数
    type_args = []
    for param_name in param_names:
        substituted_type_str = type_substitution.get(param_name)
        if substituted_type_str:
            type_args.append(_parse_substituted_type(substituted_type_str, node))
        else:
            type_args.append(TypeInfo.any())

    return (
        TypeInfo(kind=TypeKind.GENERIC, name=base_name, args=type_args)
        if type_args
        else None
    )


def _parse_generic_type_with_symbol(
    annotation: str, node: "IRNode"
) -> Optional[TypeInfo]:
    """解析泛型类型（通过符号查找）

    Args:
        annotation: 类型注解字符串
        node: 上下文节点

    Returns:
        解析后的 TypeInfo，失败返回 None
    """
    base_name, type_str_args = decode_generic_type_str(annotation)
    lookup_type_args, concrete_type_args = _parse_generic_type_args(type_str_args, node)

    # 查找符号
    # TypeVar 被注册为 VARIABLE，所以需要同时查找 CLASS 和 VARIABLE
    type_symbol = node.lookup_symbol(
        base_name,
        template_args=lookup_type_args,
        symbol_kinds=[SymbolKind.CLASS, SymbolKind.VARIABLE],
    )
    if not type_symbol:
        return None

    # 构建泛型类型
    canonical_name = _get_canonical_type_name(base_name, type_symbol)
    return TypeInfo(kind=TypeKind.GENERIC, name=canonical_name, args=concrete_type_args)


def _parse_simple_type_with_symbol(
    annotation: str, node: "IRNode"
) -> Optional[TypeInfo]:
    """解析简单类型（通过符号查找）

    Args:
        annotation: 类型注解字符串
        node: 上下文节点

    Returns:
        解析后的 TypeInfo，失败返回 None
    """
    # 查找类型符号：CLASS（普通类型）、TYPE_PARAM（TypeVar）、VARIABLE（旧的 TypeVar）
    type_symbol = node.lookup_symbol(
        annotation,
        symbol_kinds=[SymbolKind.CLASS, SymbolKind.TYPE_PARAM, SymbolKind.VARIABLE],
    )
    if not type_symbol or not type_symbol.type_info:
        return None

    # 处理弱泛型类型（如 list -> list[any]）
    type_config = getattr(type_symbol, "type_config", None)
    if type_config:
        weak_generic = _build_weak_generic_type(type_config, node)
        if weak_generic:
            return weak_generic

    return type_symbol.type_info


def parse_type(annotation: str, node: Optional["IRNode"] = None) -> Optional[TypeInfo]:
    """解析类型注解，支持符号查找

    注意：建议使用 parse_type_with_context()，它提供更强的符号感知能力

    Args:
        annotation: 类型注解字符串，如 'int', 'list[int]', 'dict[str, int]'
        node: 可选的上下文节点，用于符号查找

    Returns:
        解析后的 TypeInfo 对象，如果解析失败则返回 None
    """
    if not annotation:
        return None

    # 有节点上下文时，优先使用符号查找
    if node:
        if is_generic_type(annotation):
            result = _parse_generic_type_with_symbol(annotation, node)
            if result:
                return result
        else:
            result = _parse_simple_type_with_symbol(annotation, node)
            if result:
                return result

    return parse_type_with_context(annotation, node=node)


def get_cpp_type(type_info, node=None, registry=None) -> Optional[str]:
    """类型转换函数，从 TypeInfo 或字符串获取 C++ 类型

    Args:
        type_info: 类型信息对象或字符串
        node: 可选的上下文节点，用于作用域查找
        registry: 可选的符号注册表，避免循环依赖

    Returns:
        C++ 类型字符串，如果无法转换则返回 None
    """
    if type_info is None:
        return None

    # 处理字符串类型 - 使用符号感知的解析（重要：能识别 TypeVar）
    if isinstance(type_info, str):
        type_info = parse_type_with_context(type_info, node=node, registry=registry)
        if type_info is None:
            return None

    # 检查基本属性
    if not type_info.name:
        return None

    # 特殊处理：TypeVar 模板参数直接返回类型名
    if type_info.kind == TypeKind.TEMPLATE or type_info.kind == TypeKind.TYPE_PARAM:
        return type_info.name

    # 特殊处理：Any 类型统一映射为 mc::variant
    if type_info.kind == TypeKind.ANY:
        return "mc::variant"

    # 特殊处理：Unknown 类型（类型推导失败的情况）
    # 映射为 mc::variant（保守策略）
    if type_info.kind == TypeKind.UNKNOWN:
        return "mc::variant"

    # 特殊处理：协议类型（Protocol）
    # 协议类型用于约束，不是具体的 C++ 类型
    # 策略：
    # 1. 如果协议类型的参数中包含 TypeVar（TYPE_PARAM），生成 std::function
    # 2. 否则，统一映射为 mc::variant
    if is_protocol_type(type_info, node, registry):
        # 检查是否是带 TypeVar 的 Callable
        if type_info.name == "Callable":
            callable_cpp_type = _get_callable_cpp_type_with_typevar(
                type_info, node, registry
            )
            if callable_cpp_type:
                return callable_cpp_type

        # 普通协议类型（无 TypeVar 或不是 Callable）
        return "mc::variant"

    # 特殊处理：tuple[] 或 tuple[()] 应该生成 std::tuple<>
    if type_info.name == "tuple":
        if not type_info.args or len(type_info.args) == 0:
            # 弱类型 tuple
            return "mc::variants"
        elif len(type_info.args) == 1 and type_info.args[0].name == "()":
            # 强类型空 tuple
            return "std::tuple<>"

    # 特殊处理：list[Any] 应该生成 mc::variants
    # 这个处理在 get_cpp_type 中进行，以便在递归处理嵌套类型时正确转换
    if type_info.name == "list" and type_info.args and len(type_info.args) == 1:
        arg_type = type_info.args[0]
        if arg_type.kind == TypeKind.ANY:
            return "mc::variants"

    # 特殊处理：Pointer[T] 应该生成 T*
    if type_info.name == "Pointer" and type_info.args and len(type_info.args) > 0:
        # 递归获取类型参数的 C++ 类型
        arg_cpp_type = get_cpp_type(type_info.args[0], node, registry)
        if arg_cpp_type:
            return f"{arg_cpp_type}*"

    # 特殊处理：lambda 类型（包括嵌套函数）
    # lambda/嵌套函数支持栈/堆两种存储模式，需要根据上下文动态决定
    # 注意：只处理 type_info.name == "lambda" 的情况，普通函数走正常流程
    if type_info.kind == TypeKind.FUNCTION and type_info.name == "lambda":
        # Lambda 或嵌套函数（都使用 "lambda" 作为类型名）
        # 关键：函数作为返回类型时，始终是 mc::variant（堆分配）
        # 栈模式的检查只对变量引用有效，不对返回类型有效

        # 检查是否是 Lambda 或嵌套函数节点本身（而不是返回类型）
        is_lambda_node_itself = (
            node
            and hasattr(node, "node_type")
            and (
                node.node_type == "lambda"
                or (node.node_type == "function" and hasattr(node, "body"))
            )
        )

        if is_lambda_node_itself and node:
            # 节点本身：检查存储模式（需确保 node 支持扩展参数接口）
            if hasattr(node, "get_extension_param"):
                storage_mode = node.get_extension_param("storage_mode")
                if storage_mode == "stack":
                    # 栈模式：使用节点上已设置的具体 functor 名称
                    stack_cpp_type = node.get_extension_param("cpp_type")
                    if stack_cpp_type and stack_cpp_type != "mc::variant":
                        return stack_cpp_type

        # 其他情况（返回类型、容器元素等）：统一返回 mc::variant
        return "mc::variant"

    # 使用基于作用域的符号查找
    symbol = lookup_type_symbol(type_info, node, registry)
    if not symbol:
        return None

    if symbol.type_config:
        cpp_type = symbol.type_config.get("cpp_type")

        # 如果是已经实例化的泛型类型，直接返回 cpp_type
        # 避免重复展开类型参数导致嵌套
        if symbol.type_config.get("is_generic_instance"):
            return cpp_type

        # 如果有类型参数，需要展开类型参数
        if type_info.args:
            # 递归展开每个类型参数
            expanded_args = []
            for arg in type_info.args:
                arg_cpp_type = get_cpp_type(arg, node, registry)
                if arg_cpp_type:
                    expanded_args.append(arg_cpp_type)
                else:
                    # 如果无法展开某个参数，使用原始类型名
                    expanded_args.append(arg.name if hasattr(arg, "name") else str(arg))

            # 如果 cpp_type 包含模板参数占位符，替换它们
            # 检查是否包含模板占位符（如 T, {T}, K, {K} 等）
            has_template_placeholder = False
            if cpp_type:
                # 检查常见的模板参数名
                template_param_names = symbol.type_config.get("generic_params", [])
                if not template_param_names:
                    # 尝试从 cpp_type 推断
                    template_param_names = infer_template_params(cpp_type)

                for param in template_param_names:
                    if param in cpp_type or f"{{{param}}}" in cpp_type:
                        has_template_placeholder = True
                        break

            if has_template_placeholder and cpp_type and len(expanded_args) > 0:
                # 使用统一的模板替换函数
                result_type = substitute_template_params_with_config(
                    cpp_type, expanded_args, symbol.type_config
                )
                return result_type
            elif cpp_type:
                # cpp_type 已经完全具体化，直接返回
                return cpp_type

            # 尝试查找实例化的符号
            if registry:
                instance_symbol = registry.lookup_type_symbol(
                    type_info.name, type_info.args
                )
                if instance_symbol and instance_symbol.type_config:
                    return instance_symbol.type_config.get("cpp_type")

        # 如果没有类型参数，但 cpp_type 包含模板占位符且有 default_type，则替换
        default_type = symbol.type_config.get("default_type")
        if cpp_type and ("<" in cpp_type) and default_type:
            # 使用 default_type 替换模板参数
            # 例如：set 类型 cpp_type 是 "mcpy::set<T>"，default_type 是 "mc::variant"
            result_type = substitute_template_params_with_config(
                cpp_type, [default_type], symbol.type_config
            )
            return result_type

        if cpp_type:
            return cpp_type

    # 可能是用户自定义类型，直接用原类型名
    if symbol.kind == SymbolKind.CLASS:
        return type_info.name

    return None


def get_type_includes(type_info, node=None, registry=None) -> List[str]:
    """获取类型所需的头文件

    Args:
        type_info: 类型信息对象或字符串
        node: 可选的上下文节点，用于作用域查找
        registry: 可选的符号注册表，避免循环依赖

    Returns:
        头文件列表
    """
    if type_info is None:
        return []

    # 处理字符串类型 - 使用符号感知的解析（重要：能识别 TypeVar）
    if isinstance(type_info, str):
        type_info = parse_type_with_context(type_info, node=node, registry=registry)
        if type_info is None:
            return []

    includes = []

    # 使用基于作用域的符号查找
    symbol = lookup_type_symbol(type_info, node, registry)

    if symbol and symbol.type_config:
        config = symbol.type_config
        # 合并 includes 和 headers 字段
        includes.extend(config.get("includes", []))
        includes.extend(config.get("headers", []))

    # 处理泛型类型的递归头文件收集
    if type_info.args:
        for arg_type in type_info.args:
            arg_includes = get_type_includes(arg_type, node, registry)
            includes.extend(arg_includes)

    # 去重并返回
    return list(set(includes))


def _get_containing_function(node: Optional["IRNode"]) -> Optional["IRNode"]:
    """获取包含当前节点的函数节点

    Args:
        node: 当前节点

    Returns:
        包含的函数节点，如果不在函数中则返回 None
    """
    if not node:
        return None

    current = node
    while current:
        # 检查是否是函数节点
        if hasattr(current, "node_type") and current.node_type in (
            "function",
            "method",
        ):
            return current
        current = getattr(current, "parent", None)

    return None


def _get_callable_cpp_type_with_typevar(
    callable_type: TypeInfo, node: Optional["IRNode"], registry
) -> Optional[str]:
    """将带 TypeVar 的 Callable 转换为 C++ 类型

    规则：
    1. 所有参数和返回值都是 TypeVar → std::function<R(T1, T2, ...)>
    2. 部分是 TypeVar → mc::variant（回退）
    3. 无 TypeVar → mc::variant

    Args:
        callable_type: Callable 类型信息
        node: 当前节点（用于获取函数上下文）
        registry: 符号注册表

    Returns:
        C++ 类型字符串，如果不适用则返回 None
    """
    if not callable_type.args or not callable_type.return_type:
        return None

    # 检查是否在模板函数上下文中
    func_node = _get_containing_function(node)
    if not func_node:
        return None  # 不在函数中，无法使用模板参数

    template_params = func_node.get_extension_param("template_params")
    if not template_params:
        return None  # 不是模板函数

    # 检查参数类型是否都是 TypeVar
    all_params_typevar = all(
        arg.kind == TypeKind.TYPE_PARAM and arg.name in template_params
        for arg in callable_type.args
    )

    # 检查返回类型是否是 TypeVar
    return_is_typevar = (
        callable_type.return_type.kind == TypeKind.TYPE_PARAM
        and callable_type.return_type.name in template_params
    )

    # 当前策略（修订）：
    # 即使 Callable 包含 TypeVar，仍然使用 mc::variant
    # 原因：
    # 1. Lambda 存储为 mc::variant，调用点无法转换为 std::function<R(T)>
    # 2. 保持与 lambda 存储机制的兼容性
    # 3. 函数仍然是模板函数（其他参数使用 TypeVar），提供编译时类型安全
    #
    # 未来优化（可选）：
    # - 在特定场景（如直接传递函数对象）可以优化为 std::function
    # - 需要更复杂的类型转换和重载解析

    return None  # 使用 mc::variant，由外层协议类型处理


def is_protocol_type(type_info: Optional[TypeInfo], node=None, registry=None) -> bool:
    """判断类型是否是协议类型

    协议类型（Protocol）用于约束和辅助推导，但不是具体类型。
    实际类型应该通过推导得到。

    这个函数利用符号系统的 is_protocol 标记，避免硬编码协议名称列表。
    查找策略与 lookup_type_symbol 一致：优先使用 node 查找，然后才是 registry。

    Args:
        type_info: 类型信息
        node: 上下文节点（用于符号查找）
        registry: 符号注册表（用于符号查找）

    Returns:
        bool: 是否是协议类型
    """
    if not type_info:
        return False

    # 检查 TypeInfo 自身的 is_protocol 标记
    if type_info.is_protocol:
        return True

    # 通过符号系统查找基础类型（不带泛型参数）
    # 因为协议类型（如 Callable[[int], int]）的 is_protocol 标记在基础类型符号中
    base_symbol = None

    # 1. 如果有上下文节点，优先从节点作用域查找
    if node is not None:
        try:
            base_symbol = node.lookup_symbol(
                type_info.name,
                symbol_kinds=[SymbolKind.CLASS, SymbolKind.TYPE_PARAM],
            )
        except Exception:
            pass

    # 2. 如果节点查找失败，从提供的 registry 查找
    if base_symbol is None and registry is not None:
        base_symbol = registry._types.get(type_info.name)

    # 3. 如果还是没找到，从全局 registry 查找
    if base_symbol is None:
        try:
            from .symbol_registry import (
                get_global_registry,
                is_global_registry_initializing,
            )

            if not is_global_registry_initializing():
                global_registry = get_global_registry()
                if registry is not global_registry:
                    base_symbol = global_registry._types.get(type_info.name)
        except Exception:
            pass

    # 检查符号的 is_protocol 配置
    if base_symbol and base_symbol.type_config:
        return base_symbol.type_config.get("is_protocol", False)

    return False


def resolve_type_annotation(
    annotated_type: Optional[TypeInfo],
    inferred_type: Optional[TypeInfo],
    node=None,
    registry=None,
) -> Optional[TypeInfo]:
    """解析类型注解，统一处理具体类型 vs 协议类型

    这是类型系统的通用机制，适用于所有注解场景：
    - 函数返回类型
    - 变量声明类型
    - 函数参数类型
    - 类属性类型

    规则：
    1. 如果注解是协议（Protocol），使用推导的实际类型
    2. 如果注解是具体类型，使用注解类型（优先级最高）
    3. 如果没有注解，使用推导类型

    查找策略与 lookup_type_symbol 一致：优先使用 node 查找，然后才是 registry。

    Args:
        annotated_type: 注解的类型（如果有）
        inferred_type: 推导的类型
        node: 上下文节点（用于符号查找）
        registry: 符号注册表（用于符号查找）

    Returns:
        最终的类型
    """
    if not annotated_type:
        # 没有注解，使用推导类型
        return inferred_type

    # 传递 node 和 registry 参数以正确查找协议类型
    if is_protocol_type(annotated_type, node, registry):
        # 协议注解：使用推导的实际类型
        # TODO: 未来可以添加协议兼容性验证
        return inferred_type
    else:
        # 具体类型注解：直接使用注解类型（优先级最高）
        return annotated_type


def lookup_type_symbol(
    type_info: TypeInfo, node=None, registry=None
) -> Optional[Symbol]:
    """基于作用域的类型符号查找函数

    Args:
        type_info: 类型信息对象
        node: 上下文节点，用于确定查找起点
        registry: 可选的符号注册表，避免循环依赖

    Returns:
        类型符号，如果找不到则返回 None
    """
    if type_info is None:
        return None

    # 1. 如果有上下文节点
    if node is not None:
        # TypeVar 被注册为 VARIABLE，所以需要同时查找 CLASS 和 VARIABLE
        symbol = node.lookup_symbol(
            type_info.name,
            template_args=type_info.args,
            symbol_kinds=[SymbolKind.CLASS, SymbolKind.VARIABLE],
        )
        if symbol:
            return symbol

    # 2. 如果提供了注册表，使用它进行查找
    if registry is not None:
        # 特殊处理：函数类型（如 lambda）查找时不带 args
        # 原因：
        # - 传统泛型（如 list[int]）：args 是模板参数，需要查找实例化符号
        # - 函数类型（如 lambda[[int], bool]）：args 是签名参数，保存在 TypeInfo 中
        # lambda 不作为泛型实例注册（如 list[int]），而是单一类型（lambda）
        lookup_args = None if type_info.kind == TypeKind.FUNCTION else type_info.args

        symbol = registry.lookup_type_symbol(type_info.name, lookup_args)
        if symbol:
            return _handle_generic_instantiation(symbol, type_info)

        # 如果在局部 registry 中找不到，尝试从全局 registry 查找内置类型
        # 但要避免在全局 registry 初始化过程中递归调用
        from .symbol_registry import (
            get_global_registry,
            is_global_registry_initializing,
        )

        if not is_global_registry_initializing():
            global_registry = get_global_registry()
            if registry is not global_registry:
                symbol = global_registry.lookup_type_symbol(type_info.name, lookup_args)
                if symbol:
                    return _handle_generic_instantiation(symbol, type_info)

    # 3. 没有注册表时返回 None，避免循环依赖
    return None


def _handle_generic_instantiation(base_symbol: Symbol, type_info) -> Symbol:
    """处理泛型类型的实例化

    Args:
        base_symbol: 基础类型符号
        type_info: 类型信息（可能包含泛型参数）

    Returns:
        实例化后的符号
    """
    # 如果不是泛型类型，直接返回基础符号
    if not type_info.args:
        return base_symbol

    # 创建泛型实例符号
    import copy

    instance_symbol = Symbol(
        name=f"{type_info.name}[{', '.join(arg.name for arg in type_info.args)}]",
        kind=base_symbol.kind,
        type_info=type_info,
        module=base_symbol.module,
        type_config=(
            copy.deepcopy(base_symbol.type_config) if base_symbol.type_config else None
        ),
        priority=base_symbol.priority,
    )

    # 复制签名（通过访问 signatures property 触发延迟初始化）
    for sig in base_symbol.signatures:
        instance_symbol.add_signature(sig)

    # 标记为泛型实例
    if instance_symbol.type_config:
        instance_symbol.type_config["is_generic_instance"] = True
        instance_symbol.type_config["template_args"] = type_info.args
        instance_symbol.type_config["base_type"] = type_info.name

    return instance_symbol


def initialize_builtin_types_to_registry(registry):
    """将内置类型初始化到符号注册表中

    Args:
        registry: SymbolRegistry 实例
    """
    from .builtin.builtin_table import BUILTIN_CONFIG, is_type_config

    # 分离基础类型、模板类型和 Protocol 类型
    primitive_types = {}
    template_types = {}
    protocol_types = {}

    for name, config in BUILTIN_CONFIG.items():
        if is_type_config(config):
            # Protocol 类型（优先判断，因为 Protocol 也可能是泛型）
            if config.get("is_protocol"):
                protocol_types[name] = config
            elif is_generic_type(name):  # 使用统一的函数
                # 模板类型：list[T], dict[K,V] 等
                base_name, _ = decode_generic_type_str(name)  # 使用统一的解析函数
                template_types[base_name] = (name, config)
            else:
                # 基础类型：int, str, bool 等
                primitive_types[name] = config

    # 注册 Protocol 类型（优先注册，因为其他类型可能引用它们）
    for name, config in protocol_types.items():
        _register_protocol_type(registry, name, config)

    # 注册基础类型
    for name, config in primitive_types.items():
        # 基础类型和模板类型是不同的，都需要注册
        # 例如：list (mc::array<mc::variant>) 和 list[T] (mc::array<T>) 是不同的类型
        _register_primitive_type(registry, name, config)

    # 注册模板类型
    for base_name, (full_name, config) in template_types.items():
        _register_template_type(registry, full_name, config)

    # 在所有类型注册完成后，处理继承关系
    # 这确保父类型已经注册
    for name, config in primitive_types.items():
        if "inherit_from" in config:
            symbol = registry._primitive_types.get(name) or registry._types.get(name)
            if symbol:
                # 填充 base_types
                base_type_name = config["inherit_from"]
                base_symbol = registry._primitive_types.get(
                    base_type_name
                ) or registry._types.get(base_type_name)
                if base_symbol and base_symbol.type_info:
                    symbol.type_info.base_types = [base_symbol.type_info]

                # 处理构造函数继承
                if not symbol.signatures:
                    # 重新调用构造函数注册，这次父类型已经存在
                    registry._register_constructors(symbol, symbol.type_config)

    # 注册类型别名
    _register_type_aliases(registry)


def _register_primitive_type(registry, name: str, config: dict) -> None:
    """注册基础类型到符号注册表"""
    cpp_type = config.get("cpp_type", "mc::variant")
    includes = config.get("includes", [])

    # 如果有类型替换配置，应用到 cpp_type
    # 例如：set 继承自 set[T]，需要将 T 替换为 mc::variant
    type_substitution = config.get("type_substitution")
    if type_substitution and cpp_type:
        for param, concrete_type in type_substitution.items():
            # 替换花括号格式和裸模板参数
            cpp_type = cpp_type.replace(f"{{{param}}}", concrete_type)
            # 处理尖括号内的裸参数：<T> -> <mc::variant>
            import re

            pattern = r"<([^<>]*)\b" + re.escape(param) + r"\b([^<>]*)>"

            def replacer(match):
                before = match.group(1)
                after = match.group(2)
                return f"<{before}{concrete_type}{after}>"

            cpp_type = re.sub(pattern, replacer, cpp_type)

    registry.register_primitive_type(
        name=name,
        cpp_type=cpp_type,
        includes=includes,
        **{k: v for k, v in config.items() if k not in ["cpp_type", "includes"]},
    )


def _register_template_type(registry, full_name: str, config: dict) -> None:
    """注册模板类型到符号注册表"""
    # 提取基础名称 - 使用统一的解析函数
    base_name, _ = decode_generic_type_str(full_name)

    # 获取 C++ 模板
    cpp_type = config.get("cpp_type", "mc::variant")
    includes = config.get("includes", [])

    # 解析模板参数（支持可变参数）
    from mcpy.builtin.builtin_table import _split_template_args
    from mcpy.template_param import TemplateParam

    type_match = re.search(r"\[([^\]]+)\]", full_name)
    if not type_match:
        return

    # 使用 _split_template_args 解析模板参数（支持可变参数）
    type_args = _split_template_args(type_match.group(1))

    template_params_str = []  # 向后兼容：字符串列表
    template_params_detailed = []  # 详细的模板参数定义
    variadic_param_index = None

    for i, arg in enumerate(type_args):
        # 检查是否为可变参数
        is_variadic = arg.endswith("...")
        param_name = arg[:-3].strip() if is_variadic else arg.strip()

        # 向后兼容：添加到字符串列表（移除 ... 后缀）
        template_params_str.append(param_name)

        # 构建详细的模板参数定义
        template_param = TemplateParam(name=param_name, is_variadic=is_variadic)
        template_params_detailed.append(template_param)

        if is_variadic:
            variadic_param_index = i

    if not template_params_str:
        return

    # 转换为新的模板格式
    cpp_template = _convert_to_template_format(cpp_type, template_params_str)

    # 检查是否为可变参数模板
    is_variadic = variadic_param_index is not None

    # 注册模板类型（向后兼容：仍使用字符串列表）
    symbol = registry.register_template_type(
        name=base_name,
        template_params=template_params_str,
        cpp_template=cpp_template,
        is_variadic=is_variadic,
        includes=includes,
        **{k: v for k, v in config.items() if k not in ["cpp_type", "includes"]},
    )

    # 保存详细的模板参数信息到符号
    if symbol:
        symbol.template_params = template_params_detailed


def _register_protocol_type(registry, name: str, config: dict) -> None:
    """注册 Protocol 类型到符号注册表

    Protocol 类型定义了类型必须实现的方法集合，用于结构化子类型检查。

    Args:
        registry: SymbolRegistry 实例
        name: Protocol 名称（如 "Comparable", "Iterable[T]"）
        config: Protocol 配置字典

    示例:
        "Comparable": {
            "is_protocol": True,
            "required_methods": ["__lt__", "__gt__", ...],
            "cpp_concept": "std::totally_ordered",
        }
    """
    # 判断是否为泛型 Protocol（如 Iterable[T]）
    if is_generic_type(name):
        # 泛型 Protocol：Iterable[T], Mapping[K, V]
        base_name, params = decode_generic_type_str(name)
        template_params = params
        is_generic = True
    else:
        # 非泛型 Protocol：Comparable, Hashable
        base_name = name
        template_params = []
        is_generic = False

    # 创建 TypeInfo
    type_info = TypeInfo(
        name=base_name,
        kind=TypeKind.PROTOCOL,
        is_protocol=True,
        required_methods=config.get("required_methods", []),
        cpp_concept=config.get("cpp_concept"),
        module=config.get("module", "typing"),
    )

    # 如果是泛型 Protocol，添加模板参数
    if is_generic:
        type_info.is_template = True
        type_info.template_params = template_params

    # 创建符号（Protocol 作为类型符号，类似抽象类）
    symbol = Symbol(
        name=base_name,
        kind=SymbolKind.CLASS,  # Protocol 作为类型使用 CLASS
        type_info=type_info,
        module=config.get("module", "typing"),
    )

    symbol.type_config = config

    # 根据是否泛型选择注册方式
    if is_generic:
        # 泛型 Protocol 注册为模板类型
        registry._template_types[base_name] = symbol
    else:
        # 非泛型 Protocol 注册为基础类型
        registry._primitive_types[base_name] = symbol

    # 同时注册到全局类型表
    registry._types[base_name] = symbol


def _parse_template_params(name: str) -> List[str]:
    """解析模板参数

    使用统一的 decode_generic_type_str 函数，避免重复实现
    """
    _, params = decode_generic_type_str(name)

    # 处理可变参数：移除 ... 后缀
    clean_params = []
    for param in params:
        if param.endswith("..."):
            clean_params.append(param[:-3])
        else:
            clean_params.append(param)

    return clean_params


def _convert_to_template_format(cpp_type: str, template_params: List[str]) -> str:
    """转换 C++ 类型为模板格式"""
    import re

    result = cpp_type

    # 将 T, K, V 等参数转换为 {T}, {K}, {V} 格式
    for param in template_params:
        pattern = r"\b" + re.escape(param) + r"\b"
        result = re.sub(pattern, f"{{{param}}}", result)

    # 处理可变参数：Args... -> {Args...}
    result = re.sub(r"\b(\w+)\.\.\.", r"{\1...}", result)

    return result


def infer_template_params(cpp_template: str) -> List[str]:
    """从 C++ 模板字符串推断参数名

    从 <...> 或 {...} 中提取参数名，用于自动识别模板参数。

    Args:
        cpp_template: C++ 模板字符串，如 "mcpy::set<T>", "mc::array<T>"

    Returns:
        推断出的参数名列表

    Examples:
        >>> infer_template_params("mcpy::set<T>")
        ["T"]
        >>> infer_template_params("mc::dict<K, V>")
        ["K", "V"]
        >>> infer_template_params("mc::array<{T}>")
        ["T"]
    """
    import re

    # 匹配尖括号内的内容
    angle_match = re.search(r"<([^<>]+)>", cpp_template)
    if angle_match:
        params_str = angle_match.group(1)
        # 分割参数，去除空格
        params = [p.strip() for p in params_str.split(",")]
        # 提取纯参数名（去除 {} 等）
        clean_params = []
        for param in params:
            # 移除花括号
            param = param.replace("{", "").replace("}", "")
            # 移除 :: 前缀（如 mc::variant）
            if "::" not in param and param.isidentifier():
                clean_params.append(param)
        return clean_params

    return []


def extract_base_template_name(cpp_type: str) -> Optional[str]:
    """从 C++ 类型中提取容器的基础模板名

    提取模板类型的基础名称，去除类型参数部分。

    Args:
        cpp_type: 容器的 C++ 类型

    Returns:
        基础模板名，如果无法提取则返回 None

    Examples:
        >>> extract_base_template_name("mc::array<int>")
        "mc::array"
        >>> extract_base_template_name("QList<QString>")
        "QList"
        >>> extract_base_template_name("mc::list<T>")
        "mc::list"
    """
    if not cpp_type:
        return None

    # 查找第一个 '<' 的位置
    template_start = cpp_type.find("<")
    if template_start > 0:
        return cpp_type[:template_start]

    # 没有模板参数，返回原类型名
    return cpp_type


def substitute_template_params(
    cpp_template: str, template_params: List[str], concrete_types: List[str]
) -> str:
    """替换模板参数为具体类型

    这是一个通用的模板参数替换函数，用于将 C++ 模板字符串中的参数占位符
    替换为具体的类型。

    Args:
        cpp_template: C++ 模板字符串，如 "mcpy::set<T>", "mc::dict<K, V>"
        template_params: 模板参数名列表，如 ["T"], ["K", "V"]
        concrete_types: 具体类型列表，如 ["int"], ["std::string", "int"]

    Returns:
        替换后的 C++ 类型字符串

    Examples:
        >>> substitute_template_params("mcpy::set<T>", ["T"], ["int"])
        "mcpy::set<int>"
        >>> substitute_template_params("mc::dict<K, V>", ["K", "V"], ["std::string", "int"])
        "mc::dict<std::string, int>"
        >>> substitute_template_params("mc::array<T>", ["T"], ["double"])
        "mc::array<double>"
    """
    import re

    if len(template_params) != len(concrete_types):
        # 参数数量不匹配，返回原始模板
        return cpp_template

    result = cpp_template

    # 按顺序替换每个模板参数
    for param, concrete_type in zip(template_params, concrete_types):
        # 处理花括号格式：{T} -> int
        result = result.replace(f"{{{param}}}", concrete_type)

        # 处理尖括号内的裸参数：<T> -> <int>
        # 使用正则确保只在尖括号内替换
        pattern = r"<([^<>]*)\b" + re.escape(param) + r"\b([^<>]*)>"

        def replacer(match):
            before = match.group(1)
            after = match.group(2)
            # 构造新的尖括号内容
            return f"<{before}{concrete_type}{after}>"

        result = re.sub(pattern, replacer, result)

    return result


def substitute_template_params_with_config(
    cpp_template: str, concrete_types: List[str], type_config: Optional[dict] = None
) -> str:
    """智能替换模板参数（配置驱动）

    这是 substitute_template_params 的高级版本，能够自动推断模板参数名。

    参数名获取策略（优先级从高到低）：
    1. 从配置的 generic_params 字段获取
    2. 从 cpp_template 中推断（使用 infer_template_params）
    3. 使用默认命名（T, K/V, 或 T0/T1/...）

    Args:
        cpp_template: C++ 模板字符串，如 "mcpy::set<T>"
        concrete_types: 具体类型列表，如 ["int"]
        type_config: 类型配置字典（可选），包含 generic_params 等

    Returns:
        替换后的 C++ 类型字符串

    Examples:
        >>> # 方式1: 使用配置
        >>> config = {"generic_params": ["T"]}
        >>> substitute_template_params_with_config("mcpy::set<T>", ["int"], config)
        "mcpy::set<int>"

        >>> # 方式2: 自动推断
        >>> substitute_template_params_with_config("mcpy::set<T>", ["int"])
        "mcpy::set<int>"

        >>> # 方式3: 默认命名
        >>> substitute_template_params_with_config("Container<?>", ["int"])
        "Container<int>"
    """
    type_config = type_config or {}

    # 1. 优先从配置获取模板参数名
    template_param_names = type_config.get("generic_params", [])

    # 2. 如果配置中没有，尝试从 cpp_template 推断
    if not template_param_names:
        template_param_names = infer_template_params(cpp_template)

    # 3. 如果还是没有，回退到通用参数名
    if not template_param_names:
        # 根据参数数量使用默认名称
        if len(concrete_types) == 1:
            template_param_names = ["T"]
        elif len(concrete_types) == 2:
            template_param_names = ["K", "V"]
        else:
            template_param_names = [f"T{i}" for i in range(len(concrete_types))]

    # 4. 使用基础函数进行替换
    return substitute_template_params(
        cpp_template, template_param_names, concrete_types
    )


def _is_variadic_template(template_params: List[str], cpp_type: str) -> bool:
    """检查是否为可变参数模板"""
    return (
        "..." in cpp_type
        or any(param.lower() in ["args", "types"] for param in template_params)
        or len(template_params) > 2
    )


def extract_typevars_from_type_string(
    type_str: str, module_typevars: set, node: Optional["IRNode"] = None
) -> List[str]:
    """从类型字符串中提取使用的TypeVar

    递归解析类型字符串，提取其中所有引用的模块级TypeVar。
    支持嵌套泛型类型，如 future[T], dict[K, V], Callable[[T], R]。

    Args:
        type_str: 类型字符串，如 'T', 'future[T]', 'dict[K, V]'
        module_typevars: 模块中定义的TypeVar集合
        node: 上下文节点（可选，用于符号查找）

    Returns:
        提取的TypeVar名列表，如 ['T'] 或 ['K', 'V']

    Examples:
        >>> extract_typevars_from_type_string('T', {'T', 'R'})
        ['T']
        >>> extract_typevars_from_type_string('future[T]', {'T', 'R'})
        ['T']
        >>> extract_typevars_from_type_string('dict[K, V]', {'K', 'V'})
        ['K', 'V']
    """
    if not type_str or not module_typevars:
        return []

    type_info = parse_type_with_context(type_str, node=node)
    if not type_info:
        return []

    return extract_typevars_from_typeinfo(type_info, module_typevars)


def extract_typevars_from_typeinfo(
    type_info: TypeInfo, module_typevars: set
) -> List[str]:
    """从TypeInfo中递归提取TypeVar

    Args:
        type_info: 类型信息
        module_typevars: 模块中定义的TypeVar集合

    Returns:
        提取的TypeVar名列表
    """
    result = []

    def collect_typevars(ti: Optional[TypeInfo]):
        """递归收集TypeInfo中的TypeVar"""
        if not ti:
            return

        # 检查是否是TypeVar
        if ti.name in module_typevars:
            if ti.name not in result:
                result.append(ti.name)

        # 递归处理泛型参数（如 list[T], Callable[[T], R]）
        if ti.args:
            for arg in ti.args:
                collect_typevars(arg)

        # 递归处理返回类型（Callable等）
        if ti.return_type:
            collect_typevars(ti.return_type)

    collect_typevars(type_info)
    return result


def _register_type_aliases(registry) -> None:
    """注册类型别名"""
    from .builtin.builtin_table import BUILTIN_CONFIG

    # 硬编码的别名（向后兼容）
    aliases = {
        "List": "list",
        "Dict": "dict",
        "Set": "set",
        "Tuple": "tuple",
    }

    # 从配置中自动提取type_alias
    for name, config in BUILTIN_CONFIG.items():
        if isinstance(config, dict) and "type_alias" in config:
            aliases[name] = config["type_alias"]

    for alias, canonical in aliases.items():
        registry.register_type_alias_new(alias, canonical)
